package com.lix.service.workflow.impl;

import com.alibaba.fastjson2.util.DateUtils;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.lix.base.BaseResult;
import com.lix.config.ProcessConfig;
import com.lix.service.workflow.IProcessDefinitionService;
import com.lix.vo.workflow.req.ProcDefiReq;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.repository.ProcessDefinitionQuery;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class ProcessDefinitionServiceImpl extends ActivitiService implements IProcessDefinitionService {

    @Autowired
    private ProcessConfigServiceImpl processConfigService;

    /**
     * 查询部署的流程定义数据列表,如果有多个相同标识key的流程时，只查询其最新版本
     *
     * @return
     */
    @Override
    public BaseResult getProcDefiList(ProcDefiReq req) {
        // 1. 获取 ProcessDefinitionQuery
        ProcessDefinitionQuery query = repositoryService.createProcessDefinitionQuery();

        // 条件查询
        if (StringUtils.isNotEmpty(req.getName())) {
            query.processDefinitionNameLike("%" + req.getName() + "%");
        }
        if (StringUtils.isNotEmpty(req.getKey())) {
            query.processDefinitionKeyLike("%" + req.getKey() + "%");
        }

        // 有多个相同标识key的流程时，只查询其最新版本
        List<ProcessDefinition> definitionList = query.latestVersion().listPage(req.getFirstResult(), req.getPageSize());
        // 用于前端显示页面，总记录数
        long total = query.count();
        // 封闭响应结果
        List<Map<String, Object>> records = new ArrayList<>();

        for (ProcessDefinition pd : definitionList) {
            Map<String, Object> data = new HashMap<>();
            data.put("id", pd.getId());
            data.put("name", pd.getName());
            data.put("key", pd.getKey());
            data.put("version", pd.getVersion());
            // 流程定义状态
            data.put("state", pd.isSuspended() ? "已暂停" : "已启动");
            // xml文件名
            data.put("xmlName", pd.getResourceName());
            // png 文件名
            data.put("pngName", pd.getDiagramResourceName());
            // 查询部署时间
            String deploymentId = pd.getDeploymentId();
            data.put("deploymentId", deploymentId);
            Deployment deployment = repositoryService.createDeploymentQuery().deploymentId(deploymentId).singleResult();
            data.put("deploymentTime", DateUtils.format(deployment.getDeploymentTime()));

            // 查询流程定义与业务关系配置信息
            ProcessConfig processConfig = processConfigService.getByProcessKey(pd.getKey());
            if (processConfig != null) {
                // 业务路由名
                data.put("businessRoute", processConfig.getBusinessRoute());
                // 表单组件名
                data.put("formName", processConfig.getFormName());
            }
            records.add(data);
        }
        Map<String, Object> result = new HashMap<>();
        result.put("total", total);
        result.put("records", records);
        return BaseResult.ok(result);
    }

    @Override
    public BaseResult updateProcDefiState(String procDefiId) {
        // 流程定义对象
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                .processDefinitionId(procDefiId)
                .singleResult();
        // 获取当前状态是否为：挂起
        boolean suspended = processDefinition.isSuspended();
        if (suspended) {
            // 如果状态是：挂起，将状态更新为：激活
            repositoryService.activateProcessDefinitionById(procDefiId, true, null);
        } else {
            // 如果状态是：激活，将状态更新为：挂起
            repositoryService.suspendProcessDefinitionById(procDefiId, true, null);
        }
        return BaseResult.ok();
    }

    @Override
    public BaseResult deleteDeployment(String deploymentId, String key) {
        // 不带级联的删除：如果有正在执行的流程，则删除失败抛出异常；不会删除 ACT_HI_和 历史表数据
        repositoryService.deleteDeployment(deploymentId);
        List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery().processDefinitionKey(key).list();

        // 没有流程定义了，删除流程配置
        if (CollectionUtils.isEmpty(list)) {
            processConfigService.deleteByProcessKey(key);
        }
        return BaseResult.ok();
    }
}
